package com.iot08.admin.utils.buckettool;

import io.minio.*;
import io.minio.errors.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
import java.util.Set;

/**
 * MiniIO 操作工具
 *
 * @Author: Weichao
 * @Date: 2024/08/26/15:57
 * @Description:
 */
@Slf4j
@Component
public class MiniIOUtilTool {

    private MinioClient.Builder minioClientBuilder;
    @Value("${miniIO.endpoint:}")
    private String endpoint;
    @Value("${miniIO.bucketName:}")
    private String bucketName;
    @Value("${miniIO.accessKey:}")
    private String accessKey;
    @Value("${miniIO.secretKey:}")
    private String secretKey;

    public static String DOMAIN;
    @Value("${miniIO.domainurl:}")
    public void setDOMAIN(String domain){
        DOMAIN = domain;
    }

    /**
     * 保存 文件到 MiniIO 上面
     * @param path
     * @param file
     * @param type
     * @throws IOException
     */
    public void upload(String path, MultipartFile file, int type) throws IOException {
        upload(path, file.getInputStream(), type);
    }

    public void upload(String path, InputStream inputStream, int type) throws IOException {
        // 设置临时文件的权限（如果需要的话，仅适用于POSIX文件系统）
        Set<PosixFilePermission> permissions = PosixFilePermissions.fromString("rw-rw-rw-");
        FileAttribute<Set<PosixFilePermission>> attrs = PosixFilePermissions.asFileAttribute(permissions);
        // 创建临时文件
        Path tempFile = Files.createTempFile(null, ".tmp", attrs);
        File file = null;
        try {
            // 将InputStream的内容写入临时文件
            Files.copy(inputStream, tempFile, StandardCopyOption.REPLACE_EXISTING);

            file = new File(tempFile.toString());
            // 上传到对应的 Bucket上的 文件目录
//            boolean res = uploadObject(path, file.getPath());
            log.info("uploadObject start path:{} locFilePath:{}", path, file.getPath());
            UploadObjectArgs.Builder builder = UploadObjectArgs.builder();
            builder.bucket(bucketName);
            builder.object(path);// 上传到对应的 Bucket上的 文件目录
            // 标记文件类型
            if (type == 1) {
                builder.contentType(BaseBucketTool.IMG_CONTENT_TYPE);
            } else if (type == 2) {
                builder.contentType(BaseBucketTool.AMR_CONTENT_TYPE);
            } else if (type == 3) {
                builder.contentType(BaseBucketTool.ZIP_CONTENT_TYPE);
            } else if (type == 4) {
                builder.contentType(BaseBucketTool.IMG_PNG_CONTENT_TYPE);
            }
            builder.filename(file.getPath()); //要上传的文件的地址

            UploadObjectArgs uploadObjectArgs = builder.build();
            MinioClient minioClient = getMinioClient();
            minioClient.uploadObject(uploadObjectArgs);
            log.info("uploadObject end path:{} locFilePath:{}", path, file.getPath());
//            log.info("文件保存成功:path: " + path);

        } catch (Exception e) {
            log.error(" 文件保存失败:path: " + path + " error:" + e.getMessage(), e);

        } finally {
            if (file != null) {
                //删除临时文件
                boolean delete = file.delete();
                if (delete) {
                    log.debug("临时文件 被成功删除 :" + tempFile);
                }
            }
        }
    }


    public boolean checkPath(String filePath) {
        if (!this.isBucketExist()) {
            return false;
        }
        GetObjectArgs.Builder builder = GetObjectArgs.builder();
        builder.bucket(bucketName);
        builder.object(filePath);

        GetObjectArgs objectArgs = builder.build();
        MinioClient minioClient = getMinioClient();
        GetObjectResponse response = null;
        try {
            response = minioClient.getObject(objectArgs);
        } catch (ErrorResponseException e) {
            if (e.response().code() == 404) {
                log.error("downloadGetFileData filePath:" + filePath + " 文件不存在");
                return false;
            }
        } catch (Exception e) {
            log.error("downloadGetFileData filePath:" + filePath + " error:" + e.getMessage(), e);
            return false;
        }
        return true;
    }

    /**
     * 删除文件
     * @param filePath
     * @return
     */
    public Boolean delFile(String filePath) {
        try {
            if (!this.isBucketExist()) {
                return false;
            }
            boolean res = removeObject(filePath);
            return res;
        } catch (Exception e) {
            log.error("删除文件失败: filePath:" + filePath + " error:" + e.getMessage(), e);
        }
        return true;
    }

    /**
     * 下载文件
     * @param objectName
     * @return
     */
    public ByteArrayOutputStream downloadFileStream(String objectName) {
        if (!this.isBucketExist()) {
            return null;
        }
        return downloadGetFileData(objectName);
    }


    public MinioClient getMinioClient() {
        if (minioClientBuilder == null) {
            if (StringUtils.isEmpty(endpoint) || StringUtils.isEmpty(accessKey) || StringUtils.isEmpty(secretKey)) {
                log.error("miniIO 配置文件读取错误 endpoint, accessKey, secretKey 有一个为空");
                return null;
            }
            MinioClient.Builder builder = MinioClient.builder();
            builder.endpoint(endpoint);
            builder.credentials(accessKey, secretKey);

            minioClientBuilder = builder;
        }
        return minioClientBuilder.build();
    }

    private boolean isBucketExist() {

        // Set the builder
        BucketExistsArgs.Builder builder = BucketExistsArgs.builder();
        builder.bucket(bucketName);

        BucketExistsArgs bucketExistsArgs = builder.build();

        try {
            boolean isExist = getMinioClient().bucketExists(bucketExistsArgs);

            if (isExist) {
//            log.info("The bucket is exist! ");
                return true;
            } else {
//            //无则创建一个?
//            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
//            log.info("Create bucket is success! {}", bucketName);
//            return true;
                log.error("The bucket is not exist! {}", bucketName);
                return false;
            }
        } catch (Exception e) {
            log.error("check bucket:" + bucketName + " error:" + e.getMessage(), e);
            return false;
        }

    }

    public boolean removeObject(String filePath) {

        /*
        getMinioClient().removeObject(RemoveObjectArgs
                .builder()
                .bucket(bucketName)
                .object(filename)
                .build());
        */

        RemoveObjectArgs.Builder builder = RemoveObjectArgs.builder();
        builder.bucket(bucketName);
        builder.object(filePath);

        RemoveObjectArgs removeObjectArgs = builder.build();
        try {
            MinioClient minioClient = getMinioClient();
            minioClient.removeObject(removeObjectArgs);
            log.info("removeObject filePath:" + filePath);
        } catch (Exception e) {
            log.error("removeObject filePath:" + filePath + " error:" + e.getMessage(), e);
            return false;
        }


        return true;
    }


    /**
     * 下载
     *
     * @param filePath MiniIO 目标 路径
     * @return
     */
    public ByteArrayOutputStream downloadGetFileData(String filePath) {
        try {
            GetObjectArgs.Builder builder = GetObjectArgs.builder();
            builder.bucket(bucketName);
            builder.object(filePath);

            GetObjectArgs objectArgs = builder.build();
        /*
        GetObjectArgs objectArgs = GetObjectArgs.builder()
            .bucket(bucketName)
            .object(filename)
            .build();
        */
            MinioClient minioClient = getMinioClient();
            GetObjectResponse response = null;
            try {
                response = minioClient.getObject(objectArgs);
            } catch (ErrorResponseException e) {
                if (e.response().code() == 404) {
                    log.error("downloadGetFileData filePath:" + filePath + " 文件不存在");
                } else {
                    log.error("downloadGetFileData filePath:" + filePath + " error:" + e.getMessage(), e);
                }
                return null;

            }

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len;
            while ((len = response.read(buffer)) > -1) {
                baos.write(buffer, 0, len);
            }
            baos.flush();
            return baos;
//        if (fbaos.size() > 0) {
//            log.info("Download file is success! filePath:{} ",filePath);
//            return fbaos.toByteArray();
//        }else{
//            return null;
//        }
        } catch (Exception e) {
            log.error("downloadGetFileData filePath:" + filePath + " error:" + e.getMessage(), e);
            return null;
        }
    }


}
